package org.bangumibuddy.security.filter;

import com.auth0.jwt.exceptions.JWTDecodeException;
import com.auth0.jwt.exceptions.TokenExpiredException;
import jakarta.servlet.FilterChain;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.bangumibuddy.config.property.JwtProperties;
import org.bangumibuddy.pojo.token.TokenData;
import org.bangumibuddy.security.entity.BangumiAuthenticationToken;
import org.bangumibuddy.utils.JwtManager;
import org.springframework.security.config.annotation.authentication.configuration.AuthenticationConfiguration;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.web.filter.OncePerRequestFilter;
import org.springframework.web.servlet.HandlerExceptionResolver;

@Slf4j
public class JwtAuthenticationFilter extends OncePerRequestFilter {

    AuthenticationConfiguration authenticationConfiguration;

    JwtProperties jwtProperties;

    private final HandlerExceptionResolver resolver;

    JwtManager jwtManager;

    public JwtAuthenticationFilter(AuthenticationConfiguration authenticationConfiguration, JwtProperties jwtProperties,HandlerExceptionResolver resolver,JwtManager jwtManager) {
        this.authenticationConfiguration = authenticationConfiguration;
        this.jwtProperties = jwtProperties;
        this.resolver = resolver;
        this.jwtManager = jwtManager;
    }

    @SneakyThrows
    @Override
    protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) {
        log.trace("请求路径为：{}", request.getRequestURI());

        try{
            // 从请求头中获取token
            String token = getToken(request);
            if (token != null && !StringUtils.isEmpty(token)) {
                log.trace("token:{}", token);
                //创建token提交给Manager验证
                BangumiAuthenticationToken authenticationToken = BangumiAuthenticationToken.unauthenticated(token);

                Authentication authenticate = authenticationConfiguration.getAuthenticationManager().authenticate(authenticationToken);
                SecurityContextHolder.getContext().setAuthentication(authenticate);
            }
        }catch (TokenExpiredException e) {
            //验证长期token，如果没过期就更新token
            log.trace("token过期");
            tryRefreshToken(request, response);
        }catch (JWTDecodeException e) {
            log.trace("token解析失败");
        }

        filterChain.doFilter(request, response);
    }

    public void tryRefreshToken(HttpServletRequest request, HttpServletResponse response) {
        try {
            String longlivedToken = getLonglivedToken(request);
            if(longlivedToken == null || StringUtils.isEmpty(longlivedToken))
                return;

            TokenData tokens = jwtManager.tryRefreshToken(longlivedToken);
            response.addHeader(jwtProperties.getTokenName(), tokens.getToken());
            response.addHeader(jwtProperties.getRefreshName(), tokens.getLonglivedToken());

            //将token提交给Manager验证
            BangumiAuthenticationToken authenticationToken = BangumiAuthenticationToken.unauthenticated(tokens.getToken());
            Authentication authenticate = authenticationConfiguration.getAuthenticationManager().authenticate(authenticationToken);
            SecurityContextHolder.getContext().setAuthentication(authenticate);
        }catch (Exception e){
            log.trace("token刷新失败");
        }
    }

    public String getToken(HttpServletRequest request) {
        try {
            return request.getHeader(jwtProperties.getTokenName());
        } catch (Exception e) {
            return null;
        }
    }

    public String getLonglivedToken(HttpServletRequest request) {
        try {
            return request.getHeader(jwtProperties.getRefreshName());
        } catch (Exception e) {
            return null;
        }
    }

}
